package com.authine.cloudpivot.ext.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.engine.domain.organization.Department;
import com.authine.cloudpivot.engine.domain.organization.DeptUser;
import com.authine.cloudpivot.engine.domain.organization.User;
import com.authine.cloudpivot.engine.enums.status.UserStatus;
import com.authine.cloudpivot.engine.enums.type.DeptType;
import com.authine.cloudpivot.engine.enums.type.GenderType;
import com.authine.cloudpivot.engine.enums.type.PrivacyLevelType;
import com.authine.cloudpivot.engine.service.organization.DepartmentService;
import com.authine.cloudpivot.engine.service.organization.DeptUserService;
import com.authine.cloudpivot.engine.service.organization.UserService;
import com.authine.cloudpivot.engine.service.organization.util.UserPinYinHelper;
import com.authine.cloudpivot.ext.service.ZcOrgService;
import com.authine.cloudpivot.ext.service.ZcSyncOrgService;
import com.authine.cloudpivot.web.api.util.DateUtils;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author hxd
 * @Date 2022/3/16 10:19
 * @Description  中车知识库项目, 自主维护组织(corpId=main), 但是需要把bpm 组织同步过来
 **/
@Service
@Slf4j
public class ZcSyncOrgServiceImpl implements ZcSyncOrgService {
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private DeptUserService deptUserService;
    @Autowired
    private UserService userService;
    @Autowired
    private Redisson redisson;
    @Autowired
    private ZcOrgService zcOrgService;
    @Value("${eac.rootId:18f923a75a5e426d94aea55ad1a4b240}")
    private String eacRootId ;

    private Department root = null;

    private final String corpId = "main";


    private Lock getLock(){
        RLock lock = redisson.getLock("zcsync");
        return lock;
    }

    @Override
    public ResponseResult fullAllSync()  {

        Lock lock = getLock();

        boolean isLock = false;

        try {
            isLock = lock.tryLock(3, TimeUnit.SECONDS);
            if (isLock) {
                log.info("============开始执行组织全量部门开始");
                //同步部门
                JSONArray deptList = zcOrgService.getAllOrg();
                List<Department> detps = syncDept(deptList);
                log.info("============执行组织全量部门同步结束");
                log.info("============执行组织全量用户及用户部门关系同步开始");
                if (CollectionUtils.isNotEmpty(detps)){
                    processSyncUser(detps);
                    log.info("============执行组织全量用户及用户部门关系同步结束");

                    //部门managerId
                    detps.stream().filter(d->Objects.nonNull(d.getManagerId())).forEach(d->{
                        User mangerUser = userService.getBySourceIdAndCorpId(d.getManagerId(), corpId);
                        if (mangerUser != null) {
                            d.setManagerId( mangerUser.getUserId());
                            departmentService.save(d);
                        }

                    });
                    log.info("刷新部门主管成功");
                }

                //刷新虚拟组织
//                virtualOrg();

                return ResponseResult.builder().errcode(0l).errmsg("成功").build();

            }else {
                return ResponseResult.builder().errcode(0l).errmsg("有其他组织同步任务在执行").build();
            }

        } catch (Exception e) {
            log.info("=========组织全量同步失败",e);
            return ResponseResult.builder().errcode(-1l).errmsg("组织同步失败:".concat(String.valueOf(e.getMessage()))).build();
        }finally {
            if (isLock) {
                lock.unlock();
            }
        }
    }

    // 刷新虚拟组织
    private  void virtualOrg(){
        log.info("刷新虚拟组织");
        List<Map<String, Object>> virtualArr = zcOrgService.getVirtualSetting();

        if (CollectionUtils.isEmpty(virtualArr)){
            log.info("虚拟组配置为空");
        }

        virtualArr.stream().flatMap(m ->  {
            String xnbm = (String) m.get("xnbm");
            String stbm = (String)m.get("stbm");

            if (StringUtils.isEmpty(xnbm) || StringUtils.isEmpty(stbm)) {
                return null;
            }

            Department dept = departmentService.get(xnbm);
            if (dept ==null){
                log.info("虚拟组织为空,id={}",xnbm);
                return null;
            }

            JSONArray subDept = JSONArray.parseArray(stbm);

            List<Department> collect = subDept.stream().map(d -> {
                Department department = departmentService.get((String) d);
                if (department == null) {
                    return null;
                }
                department.setParentId(xnbm);
                return department;
            }).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(collect)) {
                dept.setLeaf(false);
                collect.add(dept);
                return collect.stream();
            }
            return null;

        }).filter(Objects::nonNull).forEach(departmentService::save);


    }

    private void processSyncUser(List<Department> list){

        //同步用户
        list.forEach(dept->{
            JSONArray userArr = zcOrgService.getUserByDeptId(dept.getSourceId());
            if (CollectionUtils.isNotEmpty(userArr)) {
                List<User> users = syncUser(userArr,dept.getId());
                if (CollectionUtils.isNotEmpty(users)) {


                    //同步部门用户关系
                    syncDeptUser(dept.getId(),users);
                    log.info("更新用户成功,size={}",users.size());
                }
            }
        });
    }

    private List<Department> syncDept(JSONArray deptList){

        List<Department> incrDept = new ArrayList<>();
        List<Department> modifierDept = new ArrayList<>();

        deptList.stream().map(deptObj -> {
            JSONObject dept = (JSONObject) deptObj;
            String parentId = dept.getString("parentId");
            String sourceId = dept.getString("id");

            Department department = departmentService.getBySourceIdAndCorpId(sourceId,corpId);


            if (department == null) {
                if (StringUtils.isNotEmpty(parentId)) {
                    //部门新增
                    department = new Department();

                    department.setCorpId(corpId);
                    department.setDeptType(DeptType.YUNS_DEPT);
                    department.setEnabled(true);
                    department.setIsShow(true);
                    department.setSourceId(sourceId);

                    incrDept.add(department);
                } else {
                    return  null;
                }
            }else {
                modifierDept.add(department);
            }
            department.setLeaf(dept.getBoolean("leaf"));
            department.setParentId(parentId);
            department.setName(dept.getString("name"));
            String  managerId = dept.getString("managerId");
            if ( "null".equalsIgnoreCase(managerId)) managerId = null;
            department.setManagerId(managerId);

            department.setDeleted(dept.getBoolean("deleted"));

            return department;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        //新增的部门先保存并生成id
        incrDept.forEach(departmentService::save);

        //
        List<Department> depts = new ArrayList<>();
        depts.addAll(incrDept);
        depts.addAll(modifierDept);

        //匹配新增部门的 parentId
        List<Department> collect = incrDept.stream().filter(d -> Objects.nonNull(d.getParentId())).collect(Collectors.toList());

        modifierDept.addAll(collect);

        //现在的parentId 是eac里的 id, 是eac id 转 云枢id
        modifierDept.stream().filter(d-> Objects.nonNull(d.getParentId())).forEach(d->{
            if (d.getParentId().equals(eacRootId)){ // eac 里的根id
                d.setParentId(getRoot().getId());
            }else{
                Department dt = departmentService.getBySourceIdAndCorpId(d.getParentId(), corpId);
                if (dt != null) {
                    d.setParentId(dt.getId());
                }
            }
        });
        //更新部门
        modifierDept.forEach(departmentService::save);

        log.info("更新部门成功,size={}",depts.size());

        return depts;
    }



    private Department getRoot(){
        if (root == null) {
            root = departmentService.getBySourceIdAndCorpId("1_1", corpId);
        }
        return root;
    }


    private List<User> syncUser(JSONArray userList,String yunDeptId){

        List<User> updateList = userList.stream().map(userObj -> {
            JSONObject userJson = (JSONObject) userObj;

            String sourceId = userJson.getString("id");

            User user = userService.getBySourceIdAndCorpId(sourceId,corpId);

            if (user == null) {
                user = new User();
                user.setCorpId(corpId);
                user.setActive(true);
                user.setGender(GenderType.OTHER);
                user.setPrivacyLevel(PrivacyLevelType.ALL_VISIABLE);
                user.setStatus(UserStatus.ENABLE);
                user.setUsername(userJson.getString("username"));
                user.setEmployeeNo(userJson.getString("username"));
                user.setUserId(userJson.getString("username"));
                user.setName(userJson.getString("name"));
                user.setSourceId(sourceId);
                UserPinYinHelper.setUserPinYin(user);
                user.setPassword("{bcrypt}$2a$10$NvgvcocBqMn050z4nC0I6OeAhO5ERjM74pvMtSGLghPhWI5ed5myG");

            }else if(!user.getName().equals(userJson.getString("name"))){
                //重构拼音
                user.setName(userJson.getString("name"));
                UserPinYinHelper.setUserPinYin(user);
            }

//            user.setExtend1(userJson.getString("zyjszw"));
//            user.setExtend2(userJson.getString("zyjndj"));
//            user.setExtend3(userJson.getString("zyfzdj"));
//            user.setExtend4(userJson.getInteger("zwcj"));

            user.setDepartmentId(yunDeptId);
            user.setMobile(userJson.getString("mobile"));
            user.setDeleted(userJson.getBoolean("deleted"));

            return user;
        }).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(updateList)) {
            updateList.forEach(userService::save);
        }


        return updateList;
    }

    private Object syncDeptUser(String deptId,List<User> userList){

        //获取部门用户关系
        List<DeptUser> deptUserList = deptUserService.getListByUserIds(userList.stream().map(User::getId).collect(Collectors.toList()));


        //需要通过用户id 删除部门关系的用户id
        List<String> deleteUserIdList = userList.stream().filter(User::getDeleted).map(User::getId).collect(Collectors.toList());

        //需要修改的部门关系
        List<DeptUser> needUpdateList = deptUserList.stream().filter(deptUser -> !deptUser.getDeptId().equals(deptId) && !deleteUserIdList.contains(deptUser.getUserId()))
                .map(deptUser -> {
                    deptUser.setDeptId(deptId);
                    return deptUser;
                }).collect(Collectors.toList());

        //需要添加的部门关系的用户
        List<String> userIdList = deptUserList.stream().map(DeptUser::getUserId).collect(Collectors.toList());
        List<DeptUser> addList = userList.stream().filter(user -> !user.getDeleted() && !userIdList.contains(user.getId()))
                .map(user -> {
                    DeptUser deptUser = new DeptUser();
                    deptUser.setUserId(user.getId());
                    deptUser.setDeptId(deptId);
                    deptUser.setMain(true);
                    return deptUser;
                }).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(deleteUserIdList)) {
            deleteUserIdList.forEach( deptUserService::delete);
        }
        if (CollectionUtils.isNotEmpty(needUpdateList)){
            deptUserService.batchUpdateDeptUser(needUpdateList);
        }
        if (CollectionUtils.isNotEmpty(addList)){
            deptUserService.batchUpdateDeptUser(addList);
        }

        return null;
    }


    protected String sourceIdGenerator() {
        String sourceId = DateUtils.getCurrentTimeStamp() + RandomUtil.randomNumbers(3);
        return "CP" + sourceId;
    }



    @Override
    public ResponseResult syncSection(List<String> orgIds){

        Lock lock = getLock();

        boolean isLock = false;

        try {
            isLock = lock.tryLock(3, TimeUnit.SECONDS);

            if (isLock) {
                log.info("===============部分组织同步开始");

                List<Department> depts = departmentService.getListByIds(orgIds,false);

                List<String> deptSourceIds = depts.stream().map(Department::getSourceId).collect(Collectors.toList());

                JSONArray deptArr = zcOrgService.getorgByPid(deptSourceIds);


                if (CollectionUtils.isNotEmpty(deptArr)) {
                    log.info("===============部分组织用户同步开始");
                    List<Department> detps = syncDept(deptArr);
                    log.info("===============部分组织同步结束");

                    if (CollectionUtils.isNotEmpty(detps)) {
                          processSyncUser(detps);
                    }
                    log.info("===============部分组织用户同步结束");

                    //部门managerId
                    detps.stream().filter(d->Objects.nonNull(d.getManagerId())).forEach(d->{
                        User mangerUser = userService.getBySourceIdAndCorpId(d.getManagerId(), corpId);
                        if (mangerUser != null) {
                            d.setManagerId( mangerUser.getUserId());
                            departmentService.save(d);
                        }

                    });
                    log.info("刷新部门主管成功");
                }

                //刷新虚拟组织
//                virtualOrg();

                return ResponseResult.builder().errcode(0l).errmsg("成功").build();

            }else {
                return ResponseResult.builder().errcode(0l).errmsg("有其他组织同步任务在执行").build();
            }

        } catch (Exception e) {
            return ResponseResult.builder().errcode(-1l).errmsg("组织同步失败:".concat(e.getMessage())).build();
        }finally {
            if (isLock) {
                lock.unlock();
            }
        }



    }
}
